﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using YaAppoint.Common;
using YaAppoint.Response;

namespace YaAppoint.Rules
{
    [RemoteService(isEnabled: false)]
    public class RuleAppService(IRepository<RuleGroup, Guid> ruleGroupRepository,
                                IRepository<Rule,Guid> ruleRepsitory,
                                IMapper mapper,
                                ICommonAppService commonAppService,
                                AsyncQueryableExecuter queryableExecuter) : ApplicationService,IRuleAppService,ITransientDependency
    {
        private readonly IRepository<RuleGroup, Guid> _ruleGroupRepository = ruleGroupRepository;
        private readonly IRepository<Rule, Guid> _ruleRepository = ruleRepsitory;
        private readonly IMapper _mapper = mapper;
        private readonly AsyncQueryableExecuter _queryableExecuter= queryableExecuter;
        private readonly ICommonAppService _commonAppService = commonAppService;

        /// <summary>
        /// 获取所属层级选项
        /// </summary>
        public BackJson GetLevelOptions()
        { 
            List<object> data = new List<object>();
            foreach (var val in Enum.GetValues(typeof(RuleLevel)))
            {
                var option = new
                {
                    label =_commonAppService.GetEnumValueDescription(val),
                    value = Convert.ToInt32(val)
                };
                data.Add(option);
            }
            return new BackJson()
            {
                code = 0,
                data = data
            };
        }

        /// <summary>
        /// 获取逻辑类型选项
        /// </summary>
        public BackJson GetLogicTypeOptions()
        {
            List<object> data = new List<object>();
            foreach (var val in Enum.GetValues(typeof(LogicType)))
            {
                var option = new
                {
                    label = _commonAppService.GetEnumValueDescription(val),
                    value = Convert.ToInt32(val)
                };

                data.Add(option);
            }
            return new BackJson()
            {
                code = 0,
                data = data
            };
        }

        /// <summary>
        /// 获取规则详情
        /// </summary>
        public async Task<BackJson> GetRuleDetail(Guid id)
        {
            var rule = await _ruleRepository.FirstOrDefaultAsync(r => r.Id == id);
            if (rule == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleNotExist);
            }
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<Rule, RuleDto>(rule)
            };
        }

        /// <summary>
        /// 获取规则组详情
        /// </summary>
        public async Task<BackJson> GetRuleGroupDetail(Guid id)
        {
            var ruleGroup = await _ruleGroupRepository.FirstOrDefaultAsync(rg => rg.Id == id);
            if (ruleGroup == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleGroupNotExist);
            }
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<RuleGroup, RuleGroupDto>(ruleGroup)
            };
        }

        /// <summary>
        /// 加载规则组选项
        /// </summary>
        public async Task<BackJson> LoadRuleGroupOptions(RuleLevel level, Guid? depId, Guid? deviceTypeId, Guid? deviceId)
        {
            var query = await _ruleGroupRepository.GetQueryableAsync();
            switch (level)
            {
                case RuleLevel.Global:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == null && rg.DeviceTypeId == null && rg.DeviceId == null);
                    break;

                case RuleLevel.Department:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == null && rg.DeviceId == null);
                    break;

                case RuleLevel.DeviceType:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == deviceTypeId && rg.DeviceId == null);
                    break;

                case RuleLevel.Device:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == deviceTypeId && rg.DeviceId == deviceId);
                    break;
            }
            query = query.OrderByDescending(rg => rg.Order);

            var list =await  _queryableExecuter.ToListAsync(query);

            return new BackJson()
            {
                code = 0,
                data = list.Select(rg=>new { 
                    label=rg.Name,
                    value = rg.Id
                })
            };
        }

        public async Task<BackJson> LoadTableData(RuleLevel level, Guid? depId, Guid? deviceTypeId, Guid? deviceId)
        {
            var query = await _ruleGroupRepository.GetQueryableAsync();
            switch (level)
            {
                case RuleLevel.Global:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == null && rg.DeviceTypeId == null && rg.DeviceId == null);
                    break;

                case RuleLevel.Department:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == null && rg.DeviceId == null);
                    break;

                case RuleLevel.DeviceType:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == deviceTypeId && rg.DeviceId == null);
                    break;

                case RuleLevel.Device:
                    query = query.Where(rg => rg.Level == level && rg.DepartmentId == depId && rg.DeviceTypeId == deviceTypeId && rg.DeviceId == deviceId);
                    break;
            }
            query = query.OrderByDescending(rg => rg.Order);
            query = query.Include(rg => rg.Rules)
                         .Include(rg => rg.Department)
                         .Include(rg => rg.DeviceType)
                         .Include(rg => rg.Device);
            
            var list = await _queryableExecuter.ToListAsync(query);
            return new BackJson()
            {
                code=0,
                data = _mapper.Map<List<RuleGroup>,List<RuleGroupDto>>(list)
            };
        }


        /// <summary>
        /// 提交新建规则
        /// </summary>
        public async Task<BackJson> RuleCreateSubmit(RuleCreateDto dto)
        {
            var rule = _mapper.Map<RuleCreateDto, Rule>(dto);
            await _ruleRepository.InsertAsync(rule);

            return new BackJson()
            {
                code = 0,
                msg="规则已保存"
            };
        }

        /// <summary>
        /// 提交规则修改
        /// </summary>
        public async Task<BackJson> RuleEditSubmit(RuleDto dto)
        {
            var rule = await _ruleRepository.FirstOrDefaultAsync(r=>r.Id==dto.Id);
            if (rule == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleNotExist);
            }
            _mapper.Map(dto, rule);
            await _ruleRepository.UpdateAsync(rule);
            return new BackJson()
            {
                code = 0,
                msg="规则保存成功"
            };
        }

        /// <summary>
        /// 删除规则
        /// </summary>
        public async Task<BackJson> DeleteRule(Guid id)
        {
            var rule = await _ruleRepository.FirstOrDefaultAsync(r => r.Id == id);
            if (rule == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleNotExist);
            }
            await _ruleRepository.DeleteAsync(rule);
            return new BackJson()
            {
                code = 0,
                msg = "规则删除成功"
            };
        }

        /// <summary>
        /// 提交新建规则组
        /// </summary>
        public async Task<BackJson> RuleGroupCreateSubmit(RuleGroupCreateDto dto)
        {
            var ruleGroup = _mapper.Map<RuleGroupCreateDto, RuleGroup>(dto);
            await _ruleGroupRepository.InsertAsync(ruleGroup);
            return new BackJson()
            {
                code = 0,
                msg="规则组新建成功"
            };
        }

        public async Task<BackJson> RuleGroupEditSubmit(RuleGroupDto dto)
        {
            var ruleGroup = await _ruleGroupRepository.FirstOrDefaultAsync(rg => rg.Id == dto.Id);
            if (ruleGroup == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleGroupNotExist);
            }
            _mapper.Map(dto, ruleGroup);

            return new BackJson()
            {
                code = 0
            };
        }

        /// <summary>
        /// 删除规则组
        /// </summary>
        public async Task<BackJson> DeleteRuleGroup(Guid id)
        {
            var ruleGroup = await _ruleGroupRepository.FirstOrDefaultAsync(rg => rg.Id == id);
            if (ruleGroup == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleGroupNotExist);
            }
            else
            {
                if (ruleGroup.Rules != null && ruleGroup.Rules.Count > 0)
                {
                    foreach (var rule in ruleGroup.Rules)
                    {
                        await _ruleRepository.DeleteAsync(rule);
                    }
                }
                await _ruleGroupRepository.DeleteAsync(id);
            }
            return new BackJson()
            {
                code = 0,
                msg = "规则组删除成功"
            };
        }

        /// <summary>
        /// 获取指定规则组下规则列表
        /// </summary>
        public async Task<BackJson> GetGroupRules(Guid groupId)
        {
            var query = await _ruleGroupRepository.GetQueryableAsync();
            query = query.Where(rg => rg.Id == groupId).Include(rg => rg.Rules);
            var group = await _queryableExecuter.FirstOrDefaultAsync(query);
            if (group == null)
            {
                throw new BusinessException(CustomErrorCodes.RuleGroupNotExist);
            }
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<RuleGroup, RuleGroupDto>(group!).Rules!.OrderBy(r=>r.LogicType).ThenByDescending(r=>r.Order).ToList()
            };
        }
    }
}
